系列:30 天用 Google AI 打造臺灣防災速報 App(Day 8/30)
第二週進入 AI 核心。今天的任務只有一個:設計出能穩定產出「口語化災害速報」的 prompt(給模型的指示文字)。聽起來是小事,但速報是 AI 產生的文字裡,第一個會直接顯示在使用者鎖定畫面上的內容,每個字都要斟酌。
寫 prompt 之前先想清楚驗收標準,否則修改時只會「感覺這版比較好」。一則好的災害速報應該:
這四條之後會變成品質評估的檢核規則,今天先當作設計依據。
拿 8 月 22 日上午的一則真實地震示警當材料。NCDR 示警資料裡的摘要只有一句:
08/22 11:40 臺灣東部海域發生規模 5.1 有感地震,最大震度宜蘭縣南澳、花蓮縣和平、宜蘭縣宜蘭市 3 級。
順著 cap_link 欄位的網址下載完整的 CAP 電文(官方發布示警用的標準格式檔),資訊多很多:發震時間 11:40:15、震央北緯 24.42 度、東經 121.99 度、深度 27.8 公里、芮氏規模 5.1、各縣市最大震度逐一列出(宜蘭縣、花蓮縣 3 級;新北市、臺北市、桃園市、新竹縣、臺中市、彰化縣、南投縣 2 級;基隆市、新竹市、苗栗縣、雲林縣、嘉義縣、嘉義市 1 級),CAP 電文裡的官方 severity(嚴重程度)欄位標 Minor(輕微)、alert_color(警示顏色)是綠色。
這段原文有兩個特徵。第一,資訊以參數表的形式列出,沒有寫成句子。第二,15 個縣市的震度一字排開,一般民眾不會逐一去讀。速報要做的事,就是從這張表裡挑出對使用者有意義的幾個關鍵事實,寫成一句一般民眾看得懂的話。
我先把上面那些參數整理成一段文字,當作每個版本共用的輸入:
REPORT = """發震時間:2026年8月22日11時40分15秒
震央位置:北緯24.42度、東經121.99度,宜蘭縣政府東南方41.7公里(位於臺灣東部海域)
芮氏規模:5.1
地震深度:27.8公里
各地最大震度:宜蘭縣3級、花蓮縣3級、新北市2級、桃園市2級、臺中市2級、南投縣2級、新竹縣2級、臺北市2級、彰化縣2級、基隆市1級、苗栗縣1級、新竹市1級、嘉義縣1級、雲林縣1級、嘉義市1級
官方severity:Minor alert_color:綠色"""
呼叫的程式只有幾行。prompt 是各個版本的指示文字,後面接上這份報告;換版本時只改第一行:
from google import genai
prompt = f"把這則地震報告改寫成白話文。\n\n地震報告:\n{REPORT}" # 第一版
client = genai.Client()
resp = client.models.generate_content(
model="gemini-3.1-flash-lite",
contents=prompt,
config={"temperature": 0.2}, # 溫度的說明在後面
)
print(resp.text.strip())
下面引用的輸出,都是 9/19 用同一支程式實際執行的紀錄。模型每次的輸出會有些不同,重新執行時文字細節可能和這裡不一樣。
第一版,太自由:
把這則地震報告改寫成白話文。
問題:模型會自行補充內容,而且補的是判斷。這一次的輸出共 361 字,加了「【地震快訊】」標題和好幾個粗體條列項目,結尾寫下「請民眾不必過度驚慌,但仍需留意後續可能發生的餘震」。這一版每次執行的長度都不一樣,我在不同時間執行過幾次,長度在 289 到 361 字之間,但每一次的結尾都有「請大家不用擔心」「不必過度驚慌」這類的話。這些話原文沒有,這正是我們最不想要的:模型替使用者決定了該不該擔心。
第二版,加限制:
把這則地震報告改寫成白話文。只能使用報告中出現的資訊,不得推測或補充。
問題:自行補充的內容消失了,但長度沒有受到控制。這一次的輸出是 273 字,模型為了「完整」把 15 個縣市的震度分三級全部列出,還照抄了「官方評級為輕微(Minor),警示燈號為綠色」。資訊都忠於原文,但推播通知放不下,也沒有人會在鎖定畫面上讀完。
第三版,加上角色、受眾、格式與規則:
你是臺灣防災速報編輯。將官方地震報告改寫成給一般民眾的速報。
規則:
- 60 字以內,一段文字,不用條列
- 依序包含:發震時間、震央位置、規模、最大震度與地區
- 震度只寫最大震度與其縣市,其餘縣市不列
- 只能使用報告中出現的資訊,不得推測或補充
- 語氣冷靜清楚,不使用驚嘆號
- 若報告中有「無海嘯威脅」等官方判定,必須保留
地震報告:
{report}
連續執行五次,輸出完全相同:
2026年8月22日11時40分,宜蘭縣政府東南方41.7公里處發生規模5.1地震,最大震度宜蘭縣、花蓮縣3級,無海嘯威脅。
62 個字(含標點),格式很理想。問題出在最後五個字:輸入的報告裡完全沒有提到海嘯,「無海嘯威脅」是模型自己寫出來的,而且五次都寫。改用預設溫度再執行五次,結果一樣,其中一次還寫成「經氣象署評估,本起地震無海嘯威脅」,氣象署並沒有做過這個評估。
原因在我寫的最後一條規則。我的用意是「官方有講的時候不要漏掉」,但規則裡出現了「無海嘯威脅」這幾個字,模型就把它當成速報應該有的內容。同一個 prompt 裡明明還有「只能使用報告中出現的資訊」,也沒有擋住。
第四版,定稿:刪掉那條規則
我試了兩種修法。第一種是把那條規則改成「報告中沒有提到的事項一律不寫;報告中若有官方的判定文字,照原文保留」。模型不再自己寫海嘯了,但我另外準備一份真的含有「本地震無海嘯威脅」的輸入來測試,五次裡只有兩次保留,並不可靠。
第二種是直接刪掉那條規則,其他不變。連續執行五次,輸出完全相同:
2026年8月22日11時40分,臺灣東部海域發生規模5.1地震,宜蘭縣與花蓮縣最大震度3級。
47 個字(含標點),四項資訊依序到齊,沒有任何原文以外的內容。定稿採用這一版。至於「官方有海嘯判定時必須保留」這個需求,改由程式處理:電文裡有這段文字時,由程式原封不動附在速報後面,不經過模型。這一段之後會處理。
四輪改寫真正改變的,是把判斷從模型手上交回給規則:寫什麼(順序)、寫多少(只列最大震度)、不寫什麼全部由規則決定,模型能自行決定的範圍縮小到用字。第三版也提醒了我另一件事:規則裡舉的例子,模型可能直接拿去用。
寫 prompt 的過程其實一直在回答一個更根本的問題:速報該不該替使用者判斷「嚴不嚴重、是否需要避難」?
人機協作的研究給了明確的警訊。人機互動領域的國際研討會 CHI 2024 有一篇研究(Salimzadeh、He 與 Gadiraju,〈Dealing with Uncertainty: Understanding the Impact of Prognostic Versus Diagnostic Tasks on Trust and Reliance in Human-AI Decision Making〉)請 258 位參與者在旅程規劃任務中使用 AI 的建議,比較人在不同任務下如何依賴 AI。摘要裡的結論是:當任務複雜、結果不確定時,人更傾向依賴 AI,但「適當依賴」(AI 對的時候相信、AI 錯的時候不相信)的程度反而比簡單、確定的任務低。(論文連結)這項研究的情境是旅程規劃,和地震速報不同,這裡只借用它的觀察,當作設計時要留意的方向。
地震速報剛好位在這兩種情境的交界:「發生了什麼」是已經發生、可以核對的事實;「你那裡還會不會搖、要不要躲」是接下來幾秒鐘的事,沒有人能預測,模型也沒有足夠的資料去判斷。如果速報用篤定的語氣說「不用擔心」,使用者沒有時間也沒有資訊去質疑它,只能照單全收。
所以本系列的速報守一條原則:只陳述事實,不代替判斷。「花蓮最大震度 3 級」可以寫;「請安心」「不必驚慌」不寫。要不要行動的門檻由明天的分級規則決定。有官方等級時直接採用;沒有官方等級時,模型只能依照一張固定的規則表來對應,不能自己訂門檻。
(本篇輸出實測於 2026-09-19,模型 gemini-3.1-flash-lite;四輪改寫的溫度皆為 0.2。)
明天 Day 9 處理「程式怎麼讀取 AI 的輸出」:用 Structured Output 讓 Gemini 直接產出符合格式的 JSON。